/*
 *   AS IS License
 * ==Naive Coders==
 */
package com.naivecoders.refex.functions;

import com.naivecoders.refex.FunctionFactory;
import java.util.ArrayList;
import java.util.List;

public abstract class AbstractFunction {

    private final FunctionFactory origin;

    public AbstractFunction(FunctionFactory origin) {
        this.origin = origin;
    }

    protected FunctionFactory getOrigin() {
        return origin;
    }

    public abstract AbstractFunction evaluate(ListFunction x) throws InvocationException;

    public FCode getCode() {
        return getOrigin().getCode(this);
    }

    protected AbstractFunction argRaw(ListFunction f, int index) throws InvocationException {
        if (f != null && f.size() > index) {
            return f.get(index);
        }

        throw new InvocationException("unexisting argument %d", index);
    }

    protected ListFunction listArg(ListFunction f, int index) throws InvocationException {
        AbstractFunction func = null;
        try {
            func =  arg(f, index);
            return (ListFunction) func;
        } catch (ClassCastException ex) {
            getOrigin().getTrail().startTrail();
            arg(f, index);
            final InvocationException ite = new InvocationException(ex, "unexpected arg %d value %s in %s %s", index, func, f.toString(), ex.getMessage());
            ite.setTrail(getOrigin().getTrail().snapshotState());
            getOrigin().getTrail().endTrail();
            throw ite;
        }
    }
    protected AbstractFunction arg(ListFunction f, int index) throws InvocationException {
        AbstractFunction func;
        if (f != null && f.size() > index) {
            func = f.get(index);
            if (func != null && func instanceof ListFunction) {
                func = func.evaluate(null);
            }
           
            return func;
        }
        throw new InvocationException("unexisting argument %d", index);
    }
    
    @Override
    public String toString() {
        return getCode().toString();
    }
}
